package pgi

// TODO:
//  - write nested dev_error
//  - handler dispatch -- do it with reflect.Type?

import (
  "io"
  "os"
  "tnet"
)

// Function pointer that reads the first byte slice and returns the other.
type DispatchFunc func(app_ctx interface{}, route string, request_bytes []byte) (response_bytes []byte)

// A single thread to read from the input stream, dispatch to handlers, and
// write to the output.

func Serve(dispatch_func DispatchFunc, app_ctx interface{},
           infile io.Reader, outfile io.Writer) {
  chunk, _ := tnet.Read(infile)
  if chunk.Tag != byte('}') {
    os.Exit(1)
  }
  pairs, _ := tnet.ParseDictChunks(chunk.Payload);
  tnet.Log("deserialized dict: %s", pairs)

  route_c, ok := pairs.Get("route")
  if !ok {
    tnet.Log("No route")
    os.Exit(1)
  }
  // TODO: assert is string on route.Tag
  route := route_c.Payload

  app_request_c, ok := pairs.Get("request")
  if !ok {
    tnet.Log("No request")
    os.Exit(1)
  }
  app_request_str := app_request_c.Payload

  app_response_str := dispatch_func(app_ctx, string(route), app_request_str);

  pgi_response := make(map[string] string)
  pgi_response["response"] = string(app_response_str)

  response_str := tnet.DumpDict(pgi_response)
  outfile.Write([]byte(response_str))
}

func ServeDefault(dispatch_func DispatchFunc, app_ctx interface{}) {
  stdin := io.Reader(os.Stdin);
  stdout := io.Writer(os.Stdout);
  Serve(dispatch_func, app_ctx, stdin, stdout)
}
